type Bar = {
  a: number;
  b: number;
}
type Foo = {
  // bar: () => Bar;
  foo: () => number;
} & ThisType<Bar>

const foo: Foo = {
  // bar: () => ({
  //   a: 10,
  //   b: 20,
  // }),
  foo() { 
    return this.a + this.b
  }
}

type ObjectDescriptor<D, M> = {
  data?: D;
  methods?: M & ThisType<D & M>; // Type of 'this' in methods is D & M
};
 
function makeObject<D, M>(desc: ObjectDescriptor<D, M>): D & M {
  let data: object = desc.data || {};
  let methods: object = desc.methods || {};
  return { ...data, ...methods } as D & M;
}
 
let obj = makeObject({
  data: {
    x: 0,
    y: 0,
    getPointer() { 
      console.log(this.x)
    }
  },
  methods: {
    moveBy(dx: number, dy: number) {
      this.x += dx;
      this.y += dy;
    },
    moveTo() { 
      console.log(this.x);
    }
  },
});